/**
 * auth: zhukaijun
 * date: 2021-7-2
 * des: dynamics and static route menu builder
 */
const authComs = {
    pageA: () => 
        import("views/page/dynamics/pageA.vue"),
    pageB: () =>
        import("views/page/dynamics/pageB.vue"),
},
    staticComs = [{
        name: 'staticMenuA',
        path: '/staticMenuA',
        component: () =>
            import("views/page/static/pageA.vue"),
    },
    {
        name: 'staticMenuB',
        path: '/staticMenuB',
        component: () =>
            import("views/page/static/pageB.vue"),
    }]


import {
    menu
} from "apis/common.js";
import persistenceStore from "../utils/persistenceStore";
import routeImport from "../router/index";

const expireTime = 60 * 30,
    home = () =>
        import("views/home.vue"),
    getAttrValue = (attrs, type) => {
        for (let attr of attrs) {
            if (attr.key === type) {
                return attr.value;
            }
        }
        return '';
    }


export function routeBuild(force, route) {
    const basicRoute = {
        path: '/index',
        component: home
    };
    if (!force && window.ROUTE_LOADED) {
        return {
            then(cb) { }
        };
    }
    let router = route || routeImport;
    window.ROUTE_LOADED = 1;
    return {
        buildRoute(route, datas) {
            let children = [],
                init = 0,
                hisInitPage = 0,
                index = 0;
            if (location.hash) {
                hisInitPage = location.hash.match(/\#\/\w+/);
                try {
                    hisInitPage = hisInitPage ? hisInitPage[0].replaceAll('#', '') : hisInitPage;
                } catch (e) {
                    hisInitPage = hisInitPage ? hisInitPage[0].replace('#', '') : hisInitPage;
                }
            }
            for (let obj of datas) {
                let el = {};
                if (obj.menuAttrs) {
                    for (let attr of obj.menuAttrs) {
                        // init = hisInitPage ? hisInitPage : (init || (attr.key == 'component' ? attr.value + index : init));
                        init = hisInitPage ? hisInitPage : (init || (attr.key == 'component' ? attr.value : init));
                        el[attr.key] = attr.key == 'component' ? authComs[attr.value] : attr.value;
                    }
                    el.name = getAttrValue(obj.menuAttrs, 'component') + index++;
                    if (el['path'] && el['component']) {
                        children.push(el)
                    }
                    index++;
                }
            }
            route.children = children;
            return {
                route,
                init,
                with(coms, type) {
                    for (let r of coms) {
                        r.type = type;
                        children.push(r);
                    }
                    return this;
                }
            }
        },
        build(datas, getAttrValue, initPage) {
            let indexMapper = datas.reduce((acc, el, i) => {
                acc[el.id] = i;
                return acc;
            }, {});
            let root = [];
            datas.forEach(o => {
                o.path = getAttrValue(o.menuAttrs, 'path');
                o.component = getAttrValue(o.menuAttrs, 'component');
                o.icon = getAttrValue(o.menuAttrs, 'icon');
                if (getAttrValue(o.menuAttrs, 'type') == 'hide') {
                    return;
                }
                if (!o.parent) {
                    root.push(o);
                    return;
                }
                const parentEl = datas[indexMapper[o.parent]];
                if (parentEl) {
                    parentEl.children = [...(parentEl.children || []), o];
                }
            });
            return root;
        },
        buildMenu(datas, initPage) {
            datas = typeof datas === 'string' ? JSON.parse(datas) : datas;
            let finalMenu = this.build(datas, getAttrValue);
            return {
                list: finalMenu,
                default: initPage
            };
        },
        then(cb) {
            let hisData = persistenceStore.has("routes"),
                self = this;
            if (!force && hisData) {
                let hisRoute = self.buildRoute(basicRoute, (new Function('return ' + hisData)())).with(staticComs, 'hide');
                router.addRoute(hisRoute.route);
                cb(hisRoute.init, self.buildMenu(hisData, hisRoute.init));
                return;
            }
            menu().then(data => {
                if (data.code) {
                    cb();
                }
                let route = self.buildRoute(basicRoute, data.data).with(staticComs, 'hide');
                if (persistenceStore.getIfExits('routes', () => JSON.stringify(data.data), expireTime)) {
                    router.addRoute(route.route);
                    try {
                        cb(route.init, self.buildMenu(data.data, route.init));
                    } catch (e) {
                        cb();
                    }
                }
            }).catch(e => {
                localStorage.clear();
            });
        }
    }
}